import 'dart:async';

import 'package:dart_date/dart_date.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:get/get.dart';
import 'package:native_dart_package/http/request/exception/api_exception.dart';
import 'package:native_dart_package/http/request/exception/exception_handler.dart';
import 'package:native_dart_package/native_dart_package.dart';
import 'package:yt_devops/components/log_utils.dart';

import 'package:yt_devops/configs.dart';
import 'package:yt_devops/model/amap_poi.dart';
import 'package:yt_devops/model/device_model.dart';
import 'package:yt_devops/pages/devices/device_tab/device_detail/business_electricity_storage_device_detail/chart/strorage_power_line_chart.dart';
import 'package:yt_devops/pages/devices/device_tab/device_detail/business_electricity_storage_device_detail/business_electricity_storage_device_detail_model.dart';
import 'package:yt_devops/pages/tabs/device_tab/device_tab_controller.dart';
import 'package:yt_devops/resources/str_res_keys.dart';
import 'package:yt_devops/services/device/device_sevices.dart';
import 'package:yt_devops/services/map/map_services.dart';
import 'package:yt_devops/styles/styles.dart';
import 'package:yt_devops/utils/constants/time_formated.dart';
import 'package:yt_devops/utils/enums.dart';
import 'package:yt_devops/utils/func_utils.dart';
import 'package:yt_devops/utils/socket/use_subscribe.dart';

import 'chart/storage_trend_line_chart.dart';

class BusinessElectricityStorageDeviceDetailController extends GetxController {
  UseSubsribe subsribe = UseSubsribe();

  StreamSubscription? deviceStreamSubscription;

  DeviceServices deviceServices = Get.find();

  DateTime day = DateTime.now();

  LineChartData? storagePower;

  TrendLineChartData? storageTrend;

  String title = '';
  // 图表间隔
  int? interval;

  late int deviceId;

  //设备地址
  AmapPoi? deviceAddress;

  DeviceModel? deviceModel;

  @override
  void onInit() {
    super.onInit();

    title = Get.arguments['deviceName'];
    deviceId = Get.arguments['deviceId'];

    storageTrend = getEmptyElectricityData(DateTime.now());
    storagePower = getEmptyPowerData(DateTime.now());

    deviceStreamSubscription =
        subsribe.start([deviceId], true).stream.listen((data) {
              updateDeviceAddress(
                  lat: data['latitude'],
                  lng: data['longitude'],
                  type: deviceModel?.mapType ?? MapType.amap);
            });

    loadData();
  }

  @override
  void onReady() {}

  @override
  void onClose() {
    deviceStreamSubscription?.cancel();
    subsribe.closeListen();
  }

  updateDeviceAddress(
      {double? lat, double? lng, String? addr, required MapType? type}) async {
    if (lat != null && lng != null) {
      if (addr != null) {
        deviceAddress =
            AmapPoi(latitude: lat, longitude: lng, formattedAddress: addr);
      } else {
        deviceAddress = await MapServices.geopLatng(
            context: Get.context!,
            type: type ?? MapType.amap,
            latLng: LatLngModel(lat, lng));
      }

      update();
    }
  }

  String? axisLabel(int? interval) {
    if (interval == 0) {
      return null;
    }

    return '''
             {
              interval: function (index) { // 自定义间隔函数
                if (index % $interval === 0) { // 每两个显示一次
                  return true;
                } else {
                  return false;
                }
              },
            },
          ''';
  }

  loadData() => Configs.httpClient.requestWithLoading(() async {
        await getPowerCurve(day);
        trendTimeChange(day, StatisticUnitStatusType.day);
      });

  Future getPowerCurve(DateTime time) async {
    try {
      List<List> dataList = [];
      List<Color> colors = [];

      var param = {
        'deviceId': deviceId,
        'date': time.format(TimeFormated.dateToServierFromated),
        'visitType': 1
      };
      var data = await deviceServices.getPowerCurve(param);

      if (data == null || data.isEmpty) {
        dataList = completeData(time);
      } else {
        for (var i = 0; i < data.length; i = i + 2) {
          var model = PowerCurveModel.fromMap(data[i]);
          model.eventTs = model.eventTs!.substring(11, 16);
          dataList.add([model.eventTs, model.doubleVal]);
        }
      }

      storagePower = LineChartData(
          color: colors,
          data: dataList,
          unit: 'kW',
          max: getMax(data, max: 10),
          min: getMin(data, min: -10));

      update();
    } catch (e) {
      rethrow;
    }
  }

  double? getMax(List? data, {required double max}) {
    var maxValue = {};
    if (FuncUtils.isListEmpty(data)) {
      maxValue['doubleVal'] = 0;
    } else {
      maxValue = data!.reduce((pre, cur) {
        if (cur['doubleVal'] != null &&
            cur['doubleVal'] > (pre['doubleVal'] ?? 0)) {
          return cur;
        } else {
          return pre;
        }
      });
    }

    if (maxValue['doubleVal'] != null && maxValue['doubleVal'] > max) {
      return null;
    } else {
      return max;
    }
  }

  double? getMin(List data, {required double min}) {
    var minValue = {};
    if (FuncUtils.isListEmpty(data)) {
      minValue['doubleVal'] = 0;
    } else {
      minValue = data.reduce((pre, cur) {
        if ((cur['doubleVal'] ?? 0) > (pre['doubleVal'] ?? 0)) {
          return pre;
        } else {
          return cur;
        }
      });
    }
    if (minValue['doubleVal'] != null && minValue['doubleVal'] < min) {
      return null;
    } else {
      return min;
    }
  }

  powerTimeChange(DateTime time, StatisticUnitStatusType? timeType) =>
      Configs.httpClient.requestWithLoading(
        () async => await getPowerCurve(time),
      );

  Future trendTimeChange(
      DateTime time, StatisticUnitStatusType? timeType) async {
    try {
      DateTime? start = time, end;
      List charges = [], discharges = [];
      List<List> chargesChartData = [], dischargesChartData = [];
      List<String> xAxis = [];
      var i = 0;

      switch (timeType) {
        case StatisticUnitStatusType.day:
          start = time.startOfDay;
          end = time.endOfDay;
        case StatisticUnitStatusType.month:
          start = time.startOfMonth;
          end = start.addDays(7);

        case StatisticUnitStatusType.year:
          start = time.startOfYear;
          end = time.endOfYear;

        default:
      }

      await Future.doWhile(() async {
        var data = await deviceServices.getEssChargeDischargeTrends({
          'deviceId': deviceId,
          'type': timeType!.value,
          'startDate': start?.format(TimeFormated.dateToServierFromated),
          'endDate': end?.format(TimeFormated.dateToServierFromated),
          'visitType': 1
        });

        data ??= {'charge': [], 'discharge': []};

        var charge = data['charge']!, discharge = data['discharge']!;

        for (var i = 0; i < charge.length; i++) {
          var model = PowerTrendModel.fromMap(charge[i]);
          xAxis.add(model.getTimeLabel(timeType));
          chargesChartData.add([model.getTimeLabel(timeType), model.doubleVal]);
        }
        for (var i = 0; i < discharge.length; i++) {
          var model = PowerTrendModel.fromMap(discharge[i]);
          dischargesChartData
              .add([model.getTimeLabel(timeType), model.doubleVal]);
        }

        charges.addAll(charge);
        discharges.addAll(discharge);
        storageTrend = TrendLineChartData(
            data: [removal(chargesChartData), removal(dischargesChartData)],
            max: getMax([...charges, ...discharges], max: 10),
            min: getMin([...charges, ...discharges], min: 0),
            xAxis: xAxis,
            color: [
              Colour.green.withOpacity(0.23),
              Colour.primaryColor.withOpacity(0.23),
            ],
            lengend: [
              ResKey.totalChargingCapacity.tr,
              ResKey.totalDischargeCapacity.tr
            ],
            unit: 'kWh');
        update();
        i++;
        if (timeType == StatisticUnitStatusType.month &&
            end != start!.endOfMonth) {
          start = end;
          if (end!.addDays(7).isBefore(end!.endOfMonth)) {
            end = start!.addDays(7);
          } else {
            end = start!.endOfMonth;
          }
          return true;
        } else {
          return false;
        }
      });
    } catch (e) {
      if (e is ApiException) {
        handleException(e);
      } else {
        showError(e);
      }
    }
  }

  DateTime? getEndDate(StatisticUnitStatusType timeType, DateTime startDate) {}

  List<List> completeData(DateTime time) {
    var len = 24 * (60 / 2);
    List<List> data = [];
    time = time.startOfDay;
    do {
      data.add([time.format('Hm'), null]);
      time = time.addMinutes(2);
      len = len - 1;
    } while (len >= 1);

    return data;
  }

  /// 复杂数组去重
  List<List> removal(List<List> list) {
    final uniqueList = list.map((e) => e[0]).toSet();
    list.retainWhere((element) => uniqueList.remove(element[0]));
    return list;
  }

  LineChartData getEmptyPowerData(DateTime now) {
    return LineChartData(
        color: [], data: completeData(now), unit: 'kW', max: 10, min: -10);
  }

  getEmptyElectricityData(DateTime now) {
    List<List> charge = [], discharge = [];
    List<String> xAxis = [];
    DateTime date = now.startOfMonth;

    while (date.endOfDay != now.endOfMonth.addDays(1)) {
      var format = date.format('yyyy-MM-dd').substring(5);
      xAxis.add(format);
      charge.add([format, null]);
      discharge.add([format, null]);
      date = date.addDays(1);
      Log.d('date $date ${now.endOfMonth.addDays(1)}');
    }

    return TrendLineChartData(
        data: [charge, discharge],
        max: 10,
        min: -10,
        xAxis: xAxis,
        color: [
          Colour.green.withOpacity(0.23),
          Colour.primaryColor.withOpacity(0.23),
        ],
        lengend: [
          ResKey.totalChargingCapacity.tr,
          ResKey.totalDischargeCapacity.tr
        ],
        unit: 'kWh');
  }
}
